package Cplusplus;

/**
 * Created by Martyn on 26.06.14.
 */

import java.util.Scanner;
import java.util.Stack;

public class MainClass {
    public static int res;
    public static int Vichislenie(BinTree b)
    {
        BinTree test = b;
        res = 0;

        char ch = b.RootBT(b);
       //( System.out.println(b.RootBT(b));

        if (( '0' <= ch) && ( ch <= '9'))
        {
            return (test.RootBT(b) - 48);
        }
        else
        {
            switch (ch)
            {
                case '+':
                    res = Vichislenie(BinTree.Left(test)) + Vichislenie(BinTree.Right(test));
                    System.out.print("Результат сложения: ");
                    System.out.println(res);
                    return res;
                case '-':
                    res = Vichislenie(BinTree.Right(test)) - Vichislenie(BinTree.Left(test));
                    System.out.print("Результат вычитания: ");
                    System.out.println(res);
                    return res;
                case '*':
                    res = Vichislenie(BinTree.Left(test)) * Vichislenie(BinTree.Right(test));
                    System.out.print("Результат умножения: ");
                    System.out.println(res);
                    return res;
            }
        }
        return res;
    }
    public static int getPriority(char s)
    {
        if ((s == '(')||(s == ')'))
        {
            return 0;
        }
        if ((s == '*'))
        {
            return 2;
        }
        if ((s == '-')||(s == '+'))
        {
            return 1;
        }
        return 9;
    }
    public static BinTree InfixToBinaryTree(String infix, int infixL)
    {
        Stack treeStack = new Stack();
        MyStack myStack = new MyStack();

        for (int i = 0; i <= infixL; i++)
        {
            if ((infix.charAt(i) >= '1') && (infix.charAt(i) <= '9'))
            {
                treeStack.push(BinTree.ConsBT(infix.charAt(i), null, null));
                System.out.println("push -> " + infix.charAt(i));
                continue;
            }

            if ((infix.charAt(i) == '*')||(infix.charAt(i) == '+')||(infix.charAt(i) == '-'))
            {
                int priority  = getPriority(infix.charAt(i));
                System.out.println("push -> " + infix.charAt(i));
                while ((!myStack.isNull()) && ( getPriority(myStack.top()) >= priority))
                {
                    BinTree test = (BinTree) treeStack.pop();
                    BinTree test2 = (BinTree) treeStack.pop();
                    treeStack.push(BinTree.ConsBT(myStack.pop2(), test, test2));
                }

                myStack.push(infix.charAt(i));
            }

            if (infix.charAt(i) == '(')
            {
                myStack.push(infix.charAt(i));
                System.out.println("push -> " + infix.charAt(i));
                continue;
            }

            if (infix.charAt(i) == ')')
            {
                while (myStack.top() != '(')
                {
                    BinTree test = (BinTree) treeStack.pop();
                    BinTree test2 = (BinTree) treeStack.pop();
                    treeStack.push(BinTree.ConsBT(myStack.pop2(), test, test2));
                }
                myStack.pop();
                continue;
            }
        }

        return (BinTree) treeStack.firstElement();

    }

    public static void Correct (String infix, int infixL)
    {
        int k = 0, j = 0;

        for (int i = 0; i <= infixL - 1; i++)
        {
            if (infix.charAt(i) == '(')
            {
                j++;
            }

            if (infix.charAt(i) == ')')
            {
                j++;
            }

            if((infix.charAt(i) == '+') || (infix.charAt(i) == '-') || (infix.charAt(i) == '*'))
            {
                k++;
            }
        }

        if((j/2) == k)
        {
            System.out.println("Строка введена правильно.");
        }
        else
        {
            System.out.println("Error. Строка введена не правельно !");
            System.exit(1);
        }
    }

    public static void LKPprintBT (BinTree b, int height)
    {
        if (!BinTree.isNull(b))
        {
            if (!BinTree.isNull(BinTree.Right(b)))
            {
                LKPprintBT(BinTree.Right(b),height+1);
            }

            for (int i = 0; i < height; System.out.print("   "), i++);
            System.out.println(BinTree.RootBT(b));

            if (!BinTree.isNull(BinTree.Left(b)))
            {
                LKPprintBT(BinTree.Left(b),height+1);
            }
        }
    }

    public static BinTree Proizvodnaya(BinTree b, String z)
    {
        String x, str;
        char ch;
        res = 0;
        BinTree s, o;
        char prm = z.charAt(0);

        if (!BinTree.isNull(b))
        {
            ch = BinTree.RootBT(b);
            if (ch == prm)
            {
               // b.info = '1';
                b.setinfo('1');
            }
            if ((ch != '+')&&(ch != '-')&&(ch != '*')&&(ch != prm))
            {
                //b->info = '0';
                b.setinfo('0');
            }
            switch (ch)
            {
                case '+':
                {
                    Proizvodnaya(BinTree.Left(b), z);
                    Proizvodnaya(BinTree.Right(b), z);
                    //printResult (b);
                    break;
                }
                case '-':
                {
                    Proizvodnaya(BinTree.Left(b), z);
                    Proizvodnaya(BinTree.Right(b), z);
                    //printResult (b);
                    break;
                }
                case '*':
                {
                    s = BinTree.Copy(b);
                    o = BinTree.Copy(b);
                    //destroy(b); // FIXME: check if it is working
                    b = BinTree.ConsBT('+', o, s);
                    Proizvodnaya(BinTree.Left(BinTree.Left(b)), z);
                    Proizvodnaya(BinTree.Right(BinTree.Right(b)), z);
                    LKPprintBT(b,0);
                    break;
                }
            }
        }
        return b;
    }
    public static boolean TreeCheckKLP (BinTree b)
    {
        if (!BinTree.isNull(b))
        {

            if ( ('a' <= b.getinfo()) && (b.getinfo() <= 'z'))
            {
                return true;
            }
            TreeCheckKLP (BinTree.Left(b));
            TreeCheckKLP (BinTree.Right(b));
        }
        return false;
    }

    public static void main(String[] args)
    {
        System.out.println("Введите строку: ");
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        Correct(s, s.length());
        BinTree binTree = InfixToBinaryTree(s, s.length() - 1);
        System.out.println("Обход дерева: ");
        LKPprintBT(binTree,0);
        if(TreeCheckKLP(binTree))
        {
            System.out.println("В дереве есть буквы, считаем производную. ");
            System.out.println("Введите переменную для нахождения производной: ");
            sc = new Scanner(System.in);
            s = sc.nextLine();
            BinTree result2 = Proizvodnaya(binTree, s);
            LKPprintBT(binTree,0);
        }
        else
        {
            System.out.println("В дереве нет букв, считаем: ");
            Vichislenie(binTree);
        }
    }
}
